﻿Imports System
Imports System.Diagnostics
Imports System.Globalization
Imports System.Workflow.Runtime

Namespace System.Workflow.ComponentModel
    <Serializable> _
    Friend NotInheritable Class ActivityExecutorOperation
        Inherits SchedulableItem
        ' Methods
        Public Sub New(ByVal activity As Activity, ByVal opt As ActivityOperationType, ByVal contextId As Integer)
            MyBase.New(contextId, activity.QualifiedName)
            Me.activityName = activity.QualifiedName
            Me.operation = opt
        End Sub

        Public Sub New(ByVal activity As Activity, ByVal opt As ActivityOperationType, ByVal contextId As Integer, ByVal e As Exception)
            Me.New(activity, opt, contextId)
            Me.exceptionToDeliver = e
        End Sub

        Private Function ActivityOperationToString(ByVal operationType As ActivityOperationType) As String
            Dim str As String = String.Empty
            Select Case operationType
                Case ActivityOperationType.Execute
                    Return "Execute"
                Case ActivityOperationType.Cancel
                    Return "Cancel"
                Case ActivityOperationType.Compensate
                    Return "Compensate"
                Case ActivityOperationType.HandleFault
                    Return "HandleFault"
            End Select
            Return str
        End Function

        Public Overrides Function Run(ByVal workflowCoreRuntime As IWorkflowCoreRuntime) As Boolean
            Dim activityByName As Activity = workflowCoreRuntime.GetContextActivityForId(MyBase.ContextId).GetActivityByName(Me.activityName)
            [Using] workflowCoreRuntime.SetCurrentActivity(activityByName)
                [Using] context As ActivityExecutionContext = New ActivityExecutionContext(activityByName)
                    Dim activityExecutor As ActivityExecutor = ActivityExecutors.GetActivityExecutor(activityByName)
                    Select Case Me.operation
                        Case ActivityOperationType.Execute
                            If (activityByName.ExecutionStatus <> ActivityExecutionStatus.Executing) Then
                                goto Label_0309
                            End If
                            Try 
                                workflowCoreRuntime.RaiseActivityExecuting(activityByName)
                                Dim status As ActivityExecutionStatus = activityExecutor.Execute(activityByName, context)
                                If (status = ActivityExecutionStatus.Closed) Then
                                    context.CloseActivity
                                ElseIf (status <> ActivityExecutionStatus.Executing) Then
                                    Throw New InvalidOperationException(SR.GetString("InvalidExecutionStatus", New Object() { activityByName.QualifiedName, status.ToString, ActivityExecutionStatus.Executing.ToString }))
                                End If
                                goto Label_0309
                            Catch exception As Exception
                                WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 1, "Execute of Activity {0} threw {1}", New Object() { activityByName.QualifiedName, exception.ToString })
                                Throw
                            End Try
                            Exit Select
                        Case ActivityOperationType.Cancel
                            Exit Select
                        Case ActivityOperationType.Compensate
                            goto Label_01A4
                        Case ActivityOperationType.HandleFault
                            goto Label_0248
                        Case Else
                            goto Label_0309
                    End Select
                    If (activityByName.ExecutionStatus <> ActivityExecutionStatus.Canceling) Then
                        goto Label_0309
                    End If
                    Try 
                        Dim status2 As ActivityExecutionStatus = activityExecutor.Cancel(activityByName, context)
                        If (status2 = ActivityExecutionStatus.Closed) Then
                            context.CloseActivity
                        ElseIf (status2 <> ActivityExecutionStatus.Canceling) Then
                            Throw New InvalidOperationException(SR.GetString("InvalidExecutionStatus", New Object() { activityByName.QualifiedName, status2.ToString, ActivityExecutionStatus.Canceling.ToString }))
                        End If
                        goto Label_0309
                    Catch exception2 As Exception
                        WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 1, "Cancel of Activity {0} threw {1}", New Object() { activityByName.QualifiedName, exception2.ToString })
                        Throw
                    End Try
                Label_01A4:
                    If (activityByName.ExecutionStatus <> ActivityExecutionStatus.Compensating) Then
                        goto Label_0309
                    End If
                    Try 
                        Dim status3 As ActivityExecutionStatus = activityExecutor.Compensate(activityByName, context)
                        If (status3 = ActivityExecutionStatus.Closed) Then
                            context.CloseActivity
                        ElseIf (status3 <> ActivityExecutionStatus.Compensating) Then
                            Throw New InvalidOperationException(SR.GetString("InvalidExecutionStatus", New Object() { activityByName.QualifiedName, status3.ToString, ActivityExecutionStatus.Compensating.ToString }))
                        End If
                        goto Label_0309
                    Catch exception3 As Exception
                        WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 1, "Compensate of Activity {0} threw {1}", New Object() { activityByName.QualifiedName, exception3.ToString })
                        Throw
                    End Try
                Label_0248:
                    If (activityByName.ExecutionStatus = ActivityExecutionStatus.Faulting) Then
                        Try 
                            Dim status4 As ActivityExecutionStatus = activityExecutor.HandleFault(activityByName, context, Me.exceptionToDeliver)
                            If (status4 = ActivityExecutionStatus.Closed) Then
                                context.CloseActivity
                            ElseIf (status4 <> ActivityExecutionStatus.Faulting) Then
                                Throw New InvalidOperationException(SR.GetString("InvalidExecutionStatus", New Object() { activityByName.QualifiedName, status4.ToString, ActivityExecutionStatus.Faulting.ToString }))
                            End If
                            goto Label_0309
                        Catch exception4 As Exception
                            WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 1, "Compensate of Activity {0} threw {1}", New Object() { activityByName.QualifiedName, exception4.ToString })
                            Throw
                        End Try
                    End If
                End [Using]
            End [Using]
        Label_0309:
            Return True
        End Function

        Public Overrides Function ToString() As String
            Return String.Concat(New String() { "ActivityOperation((", MyBase.ContextId.ToString(CultureInfo.CurrentCulture), ")", Me.activityName, ", ", Me.ActivityOperationToString(Me.operation), ")" })
        End Function


        ' Fields
        Private activityName As String
        Private exceptionToDeliver As Exception
        Private operation As ActivityOperationType
    End Class
End Namespace

